魔术师发牌问题和拉丁方阵问题


本节引言:

本节继续带来的是循环链表的两个经典例子,分别是魔术师发牌问题和拉丁方阵问题!


1.魔术师发牌问题

问题描述

魔术师利用一副牌中的13张黑桃牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。”魔术师将牌堆最上面的哪张排数为1,把他翻过来正好是黑桃A,将黑桃A从牌堆抽出放在桌子上,第二次数1、2,将第一张放在牌堆最下面,第二张翻开,正好是黑桃2,也将它抽出放在桌子上。这样依次进行将13将牌全部翻出,准确无误。问牌最开始的顺序是怎样排的。
简单点说:把13张牌按照一定的顺序排好,然后依次取牌,将每次取到的牌放在最下面,情形如下:
数一次,取牌,黑桃1,放牌堆最下面
数两次,取牌,黑桃2,放牌堆最下面
数三次,取牌,黑桃3,放牌堆最下面
数四次,取牌,黑桃4,放牌堆最下面
…直到取到最后的黑桃13(黑桃K),表演结束!

问题思路

这里我们可以用到循环链表,先初始化13个结点,全设置为0,然后开始数数,数到对应的结点,判断是否
为0,为0的话插牌,不为0的话,继续后移!一时半伙也说不清楚,用表格阐述下吧,可能更容易理解
title=

代码实现

#include <stdio.h>
#include <stdlib.h>
 
#define CARD_NUM 13
 
typedef struct LNode
{
     int data;        
     struct LNode *next;  
}LNode; 
typedef struct LNode *LinkList;
 
//定义一个初始化链表的方法
LinkList ListCreate()
{
     LinkList head = NULL,p,q = head;
     int i;
     for (i = 1 ;i <= CARD_NUM;i++)
     {
         p = (LinkList)malloc(sizeof(LNode));
         p ->data = 0 ;
         if (head == NULL)head = p;
         else q ->next = p;
         q = p;
     }
     q ->next = head;
     return head;
}
 
//计算发牌顺序(核心)
void deal(LinkList L)
{
     LinkList p;
     int j;
     int countNum = 2 //记录当前应该到哪张牌
     p = L;
     p ->data = 1 ;   //第一张牌嘛,肯定是1
     while ( 1 )
     {
         for (j = 0 ;j <countnum;j++) -= "" p= "p" >next;
             if (p ->data != 0 //不为0说明这个位置已经有牌了,后移
             {
                 p ->next;
                 j--;
             }
         }
         if (p->data == 0 //不为0说明这个位置没牌,那么将牌插入,牌+1
         {
             p ->data = countNum;  
             countNum++;
             if (countNum == 14 ) break ;    //13张牌放置完毕,退出循环
         }
     }
}
 
 
int main()
{
     LinkList p = NULL;
     int i;
     p = ListCreate();
     deal(p);
     printf(牌的放置顺序为:
 
);
     for (i = 0 ;i < CARD_NUM;i++)
     {
         printf(黑桃%d ,p ->data);
         p = p ->next;
     }
     printf(
 
);
     return 0 ;
}

 


运行截图

title=


2.拉丁方阵问题

问题描述

拉丁方阵是一种n×n的方阵,方阵中恰有n种不同的元素,每种元素恰有n个,
并且每种元素在一行和一列中恰好出现一次。著名数学家和物理学家欧拉使用拉
丁字母来作为拉丁方阵里元素的符号,拉丁方阵因此而得名。
BB那么久,可能连题目都看不懂,没事,我们列下3 x 3,4 x 4,5 x 5的拉丁方阵给大家体验下
大家就知道了!
拉丁方阵图例子图:
title=
不知道你发现这样一个规律没?
比如3 x 3的拉丁方阵,第一行是1,2,3,第二行好像都向前移了一位,然后第一个元素跑到了最后面…
用循环链表不就刚好么?非常简单,下面撸下代码~

代码实现


#include <stdio.h>
#include <stdlib.h>
 
 
typedef struct LNode
{
     int data;        
     struct LNode *next;  
}LNode; 
typedef struct LNode *LinkList;
 
//定义一个初始化链表的方法
LinkList ListCreate( int n)
{
     LinkList head = NULL,p,q = head;
     int i;
     for (i = 1 ;i <= n;i++)
     {
         p = (LinkList)malloc(sizeof(LNode));
         p ->data = i;
         if (head == NULL)head = p;
         else q ->next = p;
         q = p;
     }
     q ->next = head;
     return head;
}
 
int main()
{
     LinkList p,q;
     int i,num = 0 ;
     printf(请输入您要构建的拉丁方针的规模(比如 3 * 3 ,输入 3 即可)
);
     scanf(%d,&num);
     p = ListCreate(num);
     printf(%d * %d 的拉丁方阵构建完毕,输出结果:
 
,num,num);
     for (i = 0 ;i < num;i++)
     {
         q = p;
         while ( 1 )
         {
             printf(%d  ,p ->data);
             p = p ->next;
             if (p == q) break //已经走完一轮了
         }
         p = p ->next;
         printf(
);
     }
     printf(拉丁方阵打印完毕~~
 
);
     return 0 ;
}

运行截图

title=

还是蛮简单的,看不懂的话,代码撸一遍,画图,会更加帮助你理解,动手!动手!动手!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值